﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using K9Nano.Share.Exceptions;
using K9Nano.Share.Reflection;

namespace K9Nano.Events
{
    public abstract class EventAutoProviderBase : IEventAutoProvider
    {
        public abstract IDictionary<string, Type> GetEvents();

        protected virtual IDictionary<string, Type> GetEventsOfBaseType(Type baseType)
        {
            return this.GetType()
                .Assembly
                .DefinedTypes
                .Where(x => x.IsClass && !x.IsAbstract && x.IsSubclassOf(baseType) && !x.IsGenericTypeDefinition)
                .ToDictionary(GetEventName, x => x.AsType());
        }

        protected virtual string GetEventName(TypeInfo typeInfo)
        {
            var baseType = typeof(IEventHandler);
            var interfaceType = typeInfo.ImplementedInterfaces.FirstOrDefault(x => baseType.IsAssignableFrom(x));
            if (interfaceType == null)
            {
                throw new K9Exception($"{typeInfo.FullName} is not an implementation of IEventHandler");
            }

            if (!interfaceType.IsGenericType || interfaceType.GenericTypeArguments.Length != 1)
            {
                throw new K9Exception($"{typeInfo.FullName} is not a generic implementation of IEventHandler");
            }

            return interfaceType.GetFullName();
        }
    }
}